package com.zl.learning.json.fastjson;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.parser.deserializer.ExtraProcessor;
import com.alibaba.fastjson.serializer.NameFilter;
import com.alibaba.fastjson.serializer.PropertyFilter;
import com.alibaba.fastjson.serializer.SerializeConfig;
import com.alibaba.fastjson.serializer.SimplePropertyPreFilter;
import org.junit.Test;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import static com.alibaba.fastjson.serializer.SerializerFeature.UseSingleQuotes;

public class TestFastJson {

    @Test
    public void serialize() {
        User user = new User();
        user.setId(11L);
        user.setName("西安");
        user.setCreateTime(LocalDateTime.now());
        String jsonString = JSON.toJSONString(user, UseSingleQuotes);
        System.out.println(jsonString);
    }

    @Test
    public void deserialize() {
        String jsonString = "{\"createTime\":\"2018-08-17 14:38:38\",\"id\":11,\"name\":\"西安\"}";
        User user = JSON.parseObject(jsonString, User.class);
        System.out.println(user.getName());
        System.out.println(user.getCreateTime());
    }

    @Test
    public void test1() {
        Result<User> res = new Result<>();
        res.setCode(1);
        res.setMsg("success");
        User u = new User(1L, "zhansan", LocalDateTime.now());
        res.setData(u);
        String val = JSON.toJSONString(res);
        System.out.println(val);
    }


    @Test
    public void test2() {
        String val = "{\"code\":1,\"data\":{\"createTime\":\"2019-07-03 17:25:57.637\",\"id\":1,\"name\":\"zhansan\"},\"msg\":\"success\"}";
        Result<User> res = JSON.parseObject(val, new TypeReference<Result<User>>() {
        });
//        System.out.println(formatDate(res.getData().getCreateTime()));
        System.out.println(res.getData().getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
    }

    @Test
    public void test3() {
        String time = "2019-07-03 17:25:57";
        Date date = parseDate(time);
        System.out.println(date.getDay());
    }

    @Test
    public void test4() {
        List<Date> list = new ArrayList<>();
        list.add(new Date());
        list.add(new Date());
//        String val = JSONObject.toJSONStringWithDateFormat(list, "yyyy-MM-dd HH:mm:ss");
        String val = JSON.toJSONStringWithDateFormat(list, "yyyy-MM-dd HH:mm:ss");
        System.out.println(val);
    }

    @Test
    public void test5() {
        String val = "[\"2019-07-03 17:47:31\",\"2019-07-03 17:47:31\"]";
        List<Date> list = JSON.parseObject(val, new TypeReference<List<Date>>() {
        });
        System.out.println(list.get(0).getDay());
    }

    @Test
    public void test6() {
        Result<List<JSONObject>> result = new Result<>();
        List<JSONObject> list = new ArrayList<>();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("aaa", "aaaa");
        list.add(jsonObject);
        result.setData(list);
        result.setCode(0);
        result.setMsg("success");
        System.out.println(JSON.toJSONString(result));
    }

    @Test
    public void test7() {
        String json = "{\"code\":0,\"data\":[{\"aaa\":\"aaaa\"}],\"msg\":\"success\"}";
        JSONObject result = JSON.parseObject(json, JSONObject.class);
        System.out.println(result.getString("data"));
        System.out.println(result);
    }

    @Test
    public void test8() {
//        String a = "{\"userPassword\":\"123456a\",\"userName\":\"zhangsan\",\"userId\":1}";
        String a = "{\"code\":1,\"data\":{\"userPassword\":\"2019-07-03 17:25:57.637\",\"id\":1,\"userName\":\"zhansan\"},\"msg\":\"success\"}";
        ExtraProcessor processor = (object, key, value) -> {
            User u = (User) object;
            switch (key) {
                case "userName":
                    u.setName((String) value);
                    break;
//                case "userId":
//                    u.setId(((Number) value).longValue());
//                    break;
                case "userPassword":
                    u.setPasswd((String) value);
                    break;
                default:
                    break;
            }
        };
        Result<User> u = JSON.parseObject(a, new TypeReference<Result<User>>() {
        }.getType(), processor);
        System.out.println(u);
    }

    @Test
    public void test9() {
        NameFilter nameFilter = (object, name, value) -> {
            if (object instanceof User) {
                if (name.equals("name")) {
                    return "userName";
                }
            }
            if (object instanceof ClassRoom) {
                if (name.equals("name")) {
                    return "className";
                }
            }
            return name;
        };
        PropertyFilter propertyFilter = (object, name, value) -> {
            if (object instanceof User) {
                return !name.equals("id");
            }
            return true;
        };
        SerializeConfig config = new SerializeConfig();
        config.addFilter(User.class, nameFilter);
        config.addFilter(ClassRoom.class, nameFilter);
        config.addFilter(User.class,propertyFilter);
        Result<User> result = new Result<>();
        result.setCode(1);
        result.setMsg("success");
        result.setData(new User(1L, "zhangsang", "123456", LocalDateTime.now(), Arrays.asList(new ClassRoom(1, "一班"))));
        String str = JSON.toJSONString(result, config);
        System.out.println(str);
    }

    @Test

    public void test10() {
        String a = "{\"code2\":1,\"data\":{\"classRooms\":[{\"id\":1,\"calssName\":\"一班\"}],\"createTime\":\"2019-10-17 14:52:56\",\"id\":1,\"name\":\"zhangsang\",\"passwd\":\"123456\"},\"msg\":\"success\"}";
        ExtraProcessor classRoomProcessor = (object, key, value) -> {
            if (object instanceof ClassRoom) {
                ClassRoom classRoom = (ClassRoom) object;
                if ("calssName".equals(key)) {
                    classRoom.setName((String) value);
                    System.out.println("");
                }
            }
        };
        ExtraProcessor processor = (object, key, value) -> {
            if (object instanceof UserResult) {
                UserResult u = (UserResult) object;
                switch (key) {
                    case "code2":
                        u.setCode((Integer) value);
                        break;
                    case "msg":
                        System.out.println(value);
//                        u.setCode((Integer) value);
                        break;
                }
            }
            if (object instanceof User) {
                User u = (User) object;
                switch (key) {
                    case "userName":
                        u.setName((String) value);
                        break;
                    case "userPassword":
                        u.setPasswd((String) value);
                        break;
                    case "classRooms":
                        u.setClassRoomList(JSON.parseObject(value.toString(), new TypeReference<List<ClassRoom>>() {
                        }.getType(), classRoomProcessor));
                        break;
                }
            }
        };
        UserResult u = JSON.parseObject(a, UserResult.class, processor);
        System.out.println(u);
    }

    @Test
    public void test11(){
        String msg = "{\"sn\":\"1\",\"sender\":\"0281371523AE\",\"receiver\":\"\",\"behavior\":2,\"uuid\":\"\",\"body\":[{\"state\":\"1\",\"type\":\"Rt\",\"services\":{\"1\":\"31\"}}]}";
        JSONObject object = JSON.parseObject(msg,JSONObject.class);
        System.out.println(object);
    }

    private String formatDate(Date date, String pattern) {
        return date.toInstant().atZone(ZoneId.systemDefault()).format(DateTimeFormatter.ofPattern(pattern));
    }

    private String formatDate(Date date) {
        return formatDate(date, "yyyy-MM-dd HH:mm:ss");
    }

    private Date parseDate(String str, String pattern) {
        return Date.from(LocalDateTime.parse(str, DateTimeFormatter.ofPattern(pattern)).atZone(ZoneId.systemDefault()).toInstant());
    }

    private Date parseDate(String str) {
        return parseDate(str, "yyyy-MM-dd HH:mm:ss");
    }

}
